package com.molichuxing.services.infrastructure.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.molichuxing.services.infrastructure.dto.response.CarAssetDto;
import com.molichuxing.services.infrastructure.dto.response.CarModifyDto;
import com.molichuxing.services.property.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.molichuxing.framework.dto.Paged;
import com.molichuxing.framework.dto.TabDto;
import com.molichuxing.framework.exception.BizException;
import com.molichuxing.framework.utils.ObjectCastUtil;
import com.molichuxing.services.business.dto.request.create.VehicleCreateBizDto;
import com.molichuxing.services.exception.VehicleExceptionCodeEnum;
import com.molichuxing.services.infrastructure.bean.CarBean;
import com.molichuxing.services.infrastructure.convertor.Convert;
import com.molichuxing.services.infrastructure.dao.CarMapper;
import com.molichuxing.services.infrastructure.dto.response.CarDto;
import com.molichuxing.services.infrastructure.service.CarService;

/**
 * <p>
 * 车辆表 服务实现类
 * </p>
 *
 * @author
 * @since 2019-08-15
 */
@Service("carService")
public class CarServiceImpl implements CarService {
	private static final Logger logger = LoggerFactory.getLogger(CarServiceImpl.class);

	@Resource
	private CarMapper carMapper;

	@Override
	public CarDto getCarById(Integer id) {
		return Convert.toCarBeanDto(carMapper.getById(id));
	}

	@Override
	public Map<Integer, CarDto> getCarByIds(List<Integer> ids) {
		if ((null == ids) || (ids.size() == 0)) {
			return null;
		}
		List<CarBean> carBeanList = carMapper.getByIds(ids);
		if ((null == carBeanList) || (carBeanList.size() == 0)) {
			return null;
		}
		return Convert.toCarBeanDto(carBeanList).stream()
				.collect(Collectors.toMap(CarDto::getId, a -> a, (k1, k2) -> k1));
	}

	@Override
	public CarDto getCarByVin(String vin) {
		return Convert.toCarBeanDto(carMapper.getByVin(vin));
	}

	@Override
	public CarDto getByVinLicencePlate(String vin, String licencePlate) {
		return Convert.toCarBeanDto(carMapper.getByVinLicencePlate(vin, licencePlate));
	}

	@Override
	public List<CarDto> getCarListBySearch(String vin, String licencePlate, CarsOperateStatusEnum statusEnum) {
		return Convert.toCarBeanDto(carMapper.getCarListBySearch(vin, licencePlate,
				statusEnum == null ? null : statusEnum.getValue(), null, null));
	}

	@Override
	public List<CarDto> getCarListByCarType(String vin, String licencePlate, CarsTypeEnum carsTypeEnum) {
		return Convert.toCarBeanDto(carMapper.getCarListBySearch(vin, licencePlate, null, null,
				carsTypeEnum == null ? null : carsTypeEnum.getValue()));
	}

	@Override
	public List<CarDto> getCarListBySearch(String vin, String licencePlate, Integer stockId) {
		return Convert.toCarBeanDto(carMapper.getCarListBySearch(vin, licencePlate, null, stockId, null));
	}

	@Override
	public Paged<CarDto> getCarPage(Map<String, Object> map, Integer pageNum, Integer pageSize) {
		logger.info("根据条件查询车辆列表。map ： [" + map + "]");
		Paged<CarDto> paged = new Paged<>();
		paged.setTab(getTabList(map));
		int count = carMapper.getCarPageCount(map);
		if (count <= 0) {
			return paged;
		}
		List<CarBean> result = carMapper.getCarPage(map, pageNum, pageSize);
		logger.info("根据条件查询车辆列表 出参：result： " + JSON.toJSONString(result));
		paged.setList(Convert.toCarInfoBeanDto(result));
		paged.setTotal(count);
		paged.setPageSize(pageSize);
		return paged;
	}

	@Override
	public Paged<CarDto> getCarDealerPage(Map<String, Object> map, Integer pageNum, Integer pageSize) {
		logger.info("根据条件查询车辆列表。map ： [" + map + "]");
		Paged<CarDto> paged = new Paged<>();
		paged.setTab(getDealerTabList(map));
		int count = carMapper.getCarPageCount(map);
		if (count <= 0) {
			return paged;
		}
		List<CarBean> result = carMapper.getCarPage(map, pageNum, pageSize);
		logger.info("根据条件查询车辆列表 出参：result： " + JSON.toJSONString(result));
		paged.setList(Convert.toCarInfoBeanDto(result));
		paged.setTotal(count);
		paged.setPageSize(pageSize);
		return paged;
	}

	@Override
	public int modifyLicencePlateById(Integer carId, String licencePlate, Integer subCompanyId) {
		logger.info("根据vin修改车牌信息");
		return carMapper.modifyLicencePlateById(carId, licencePlate, subCompanyId);
	}

	@Override
	public int modifyInsuranceById(Integer carId, Integer compulsory, Integer commercial) {
		return 0;
	}

	@Override
	public int modifyStockIdById(Integer carId, Integer stockId, Integer stockType) {
		return carMapper.modifyStockIdById(carId, stockId, stockType);
	}

	@Override
	public int modifyStatusById(Integer carId, CarsOperateStatusEnum carsOperateStatusEnum) {
		return carMapper.modifyStatusById(carId, carsOperateStatusEnum.getValue());
	}

	@Override
	public Integer createCar(VehicleCreateBizDto createBizDto) {
		CarBean carBean = new CarBean();
		carBean.setVin(createBizDto.getVin());
		carBean.setVehicleId(createBizDto.getVehicleId());
		carBean.setVehicleColorId(createBizDto.getColorId());
		carBean.setOwnershipId(createBizDto.getOwnershipId());
		carBean.setStatus(CarsOperateStatusEnum.NOT_RENT.getValue());
		carBean.setBusinessType(CarsBusinessTypeEnum.NO_BUSINESS.getValue());
		carBean.setVehicleType(createBizDto.getVehicleType());
		carBean.setIsInstallTbox(false);
		carBean.setIsHavePlate(false);
		carBean.setIsHaveCommercial(false);
		carBean.setIsHaveCompulsory(false);
		carBean.setPurchaseDate(LocalDateTime.now());
		carBean.setIsInStock(true);
		carBean.setIsDelete(false);
		int result = carMapper.createCar(carBean);
		if (result > 0) {
			return carBean.getId();
		}
		return -1;
	}

	@Override
	public List<CarDto> getSearchCarList(Integer stockId, Integer vehicleId, Integer carType, Integer carStatus) {
		return Convert.toCarBeanDto(carMapper.getSearchCarList(stockId, vehicleId, carType,carStatus));
	}

	@Override
	public Integer getNoDeleteCarCount() {
		return carMapper.getNoDeleteCarCount();
	}

	private List<TabDto> getDealerTabList(Map<String, Object> map) {
		List<TabDto> tabList = new ArrayList<>();
		HashMap<String, Object> paramMap = new HashMap<>();
		for (CarsOperateStatusEnum statusEnum : CarsOperateStatusEnum.values()) {
			if (statusEnum != CarsOperateStatusEnum.ALL) {
				paramMap.put("vehicleStatus", statusEnum.getValue());
			}
			paramMap.put("stockId", map.get("stockId"));
			paramMap.put("stockIds", map.get("stockIds"));
			paramMap.put("businessTypeList", Arrays.asList(0,1,2));
			int count = carMapper.getCarPageCount(paramMap);
			TabDto tabDto = new TabDto();
			tabDto.setCount(count);
			tabDto.setName(statusEnum.getName());
			tabDto.setType(statusEnum.getValue());
			tabList.add(tabDto);
		}
		return tabList;
	}

	private List<TabDto> getTabList(Map<String, Object> map) {
		List<TabDto> tabList = new ArrayList<>();
		if (null == map.get("plateStatus")) {
			map = new HashMap<>();
			Map<String, Long> carTab = carMapper.getCarTab();
			for (CarTabEnum statusEnum : CarTabEnum.values()) {
				map.put("status", statusEnum.getValue());
				TabDto tabDto = new TabDto();
				int value = statusEnum.getValue();
				Long integer = carTab.get(String.valueOf(value));
				tabDto.setCount(integer.intValue());
				tabDto.setName(statusEnum.getName());
				tabDto.setType(statusEnum.getValue());
				tabList.add(tabDto);
			}
		} else {
			for (CarLicencePlateStatusEnum statusEnum : CarLicencePlateStatusEnum.values()) {
				int count = carMapper.getCarCount(statusEnum.getValue());
				TabDto tabDto = new TabDto();
				tabDto.setCount(count);
				tabDto.setName(statusEnum.getName());
				tabDto.setType(statusEnum.getValue());
				tabList.add(tabDto);
			}
		}
		return tabList;
	}

	/**
	 * 交车修改车辆状态
	 * 
	 * @param carId
	 *            车辆id
	 * @return
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
	public Boolean modifyDeliveryCar(Integer carId) throws BizException {
		Boolean result = false;
		// 查询车辆信息
		CarBean carBean = carMapper.getById(carId);
		// 验证车辆信息
		if (carBean == null) {
			// 车辆不存在
			logger.error("[modifyDeliveryCar]车辆(" + carId + ")不存在");
			throw new BizException(VehicleExceptionCodeEnum.CAR_NOT_EXIST.getCode(),
					VehicleExceptionCodeEnum.CAR_NOT_EXIST.getMessage());
		} else if (CarsOperateStatusEnum.RENTED.getValue() == carBean.getStatus()) {
			// 车辆租赁中
			logger.error("[modifyDeliveryCar]车辆(" + carId + ")租赁中");
			throw new BizException(VehicleExceptionCodeEnum.CAR_RENTED.getCode(),
					VehicleExceptionCodeEnum.CAR_RENTED.getMessage());
		} else if (CarsOperateStatusEnum.NOT_RENT.getValue() == carBean.getStatus()) {
			// 车辆不可租
			logger.error("[modifyDeliveryCar]车辆(" + carId + ")不可租");
			throw new BizException(VehicleExceptionCodeEnum.CAR_NOT_RENT.getCode(),
					VehicleExceptionCodeEnum.CAR_NOT_RENT.getMessage());
		}
		// 修改车辆信息
		if (carMapper.modifyCarStatus(carId, CarsOperateStatusEnum.RENTED.getValue(),
				CarsOperateStatusEnum.FOR_RENT.getValue()) > 0) {
			result = true;
		}

		return result;
	}
	
	@Override
	public Paged<CarDto> getStockCarPage(Map<String, Object> map) {
		Paged<CarDto> paged = new Paged<>();
		paged.setTab(getCarTypeTabList());
		int count = carMapper.getStockCarPageCount(map);
		if (count <= 0) {
			return paged;
		}
		Integer pageNum = ObjectCastUtil.castInteger(map.get("pageNum"));
		Integer pageSize = ObjectCastUtil.castInteger(map.get("pageSize"));
		List<CarBean> result = carMapper.getStockCarPage(map, pageNum, pageSize);
		paged.setList(Convert.toCarInfoBeanDto(result));
		paged.setTotal(count);
		paged.setPageSize(pageSize);
		return paged;
	}

	/**
	 * 根据车辆业务类型查询车辆List
	 * @param carsBusinessTypeEnum
	 * @return
	 */
	@Override
	public List<CarDto> getCarsByBusinessType(CarsBusinessTypeEnum carsBusinessTypeEnum) {
		List<CarBean> carBeanList =  carMapper.getCarsByBusinessType(carsBusinessTypeEnum.getValue());
		return Convert.toCarBeanDto(carBeanList);
	}

	private List<TabDto> getCarTypeTabList() {
		List<TabDto> tabList = new ArrayList<>();
		for (CarsTypeTabEnum statusEnum : CarsTypeTabEnum.values()) {
			int count = carMapper.getCarCountByType(statusEnum.getValue());
			TabDto tabDto = new TabDto();
			tabDto.setCount(count);
			tabDto.setName(statusEnum.getName());
			tabDto.setType(statusEnum.getValue());
			tabList.add(tabDto);
		}	
		return tabList;
	}

	/**
	 * 还车修改车辆信息
	 * 
	 * @param carId
	 *            车辆id
	 * @return
	 */
	@Override
	public Boolean modifyReturnCar(Integer carId) {
		Boolean result = false;
		// 查询车辆信息
		CarBean carBean = carMapper.getById(carId);
		// 验证车辆信息
		if (carBean == null) {
			// 车辆不存在
			logger.error("[modifyReturnCar]车辆(" + carId + ")不存在");
			return false;
		} else if (CarsOperateStatusEnum.RENTED.getValue() != carBean.getStatus()) {
			// 车辆不是租赁中
			logger.error("[modifyReturnCar]车辆(" + carId + ")不是租赁中");
			return false;
		}
		// 修改车辆信息
		if (carMapper.modifyCarStatus(carId, CarsOperateStatusEnum.NOT_RENT.getValue(),
				CarsOperateStatusEnum.RENTED.getValue()) > 0) {
			result = true;
		}

		return result;
	}

	@Override
	public List<CarDto> getCarsByBusinessTypeList(List<Integer> businessTypeList) {
		List<CarBean> carBeanList =  carMapper.getCarsByBusinessTypeList(businessTypeList);
		return Convert.toCarBeanDto(carBeanList);
	}

	/**
	 * 修改车辆类型与车辆状态
	 * @param carId
	 * @param  carStatus
	 * @param vehicleType
	 * @return
	 */
	@Override
	public int 	modifyStatusAndVehicleTypeById(Integer carId, CarsOperateStatusEnum carStatus, CarsTypeEnum vehicleType) {
		return carMapper.modifyStatusAndVehicleTypeById(carId, carStatus.getValue(), vehicleType.getValue());
	}

	@Override
	public Map<Integer, Integer> getCarSumByStock(List<Integer> stockId, CarsStockTypeEnum carsStockTypeEnum) {
		Map<Integer, Integer> result = null;
		List<Map<Object, Object>> resultList = carMapper.getCarSumByStock(stockId, carsStockTypeEnum.getValue());
		if(null != resultList && resultList.size() > 0) {
			result = new HashMap<>();
			for(Map<Object, Object> map : resultList) {
                Integer stock =Integer.valueOf(String.valueOf(map.get("stockId")));
                Integer count =Integer.valueOf(String.valueOf(map.get("count")));
                result.put(stock, count);
			}
		}
		return result;
	}

	/**
	 * 车辆列表导出
	 *
	 * @param selectParams
	 * @return
	 */
	@Override
	public List<CarDto> getCarListDownload(Map<String, Object> selectParams) {
		List<CarBean> result = carMapper.getCarListDownload(selectParams);

		return Convert.toCarInfoBeanDto(result);
	}

	@Override
	public long getCarListDownloadCount(Map<String, Object> selectParams) {
		return carMapper.getCarListDownloadCount(selectParams);
	}

    @Override
    public int modify(CarModifyDto dto) {
		return carMapper.modify(Convert.toCarBean(dto));
    }

	@Override
	public List<CarDto> getByVinList(List<String> vinList) {
		List<CarBean> result = carMapper.getByVinList(vinList);
		return Convert.toCarInfoBeanDto(result);
	}
	
	@Override
	public Boolean modifyUseType(Integer carId, Integer status, Integer useType) {
		return carMapper.modifyUseType(carId, status, useType);
	}

	@Override
	public List<CarAssetDto> getFullBuyOut() {
		return carMapper.getFullBuyOut();
	}

	@Override
	public List<CarAssetDto> getOperatingVehicle() {
		return carMapper.getOperatingVehicle();
	}

	@Override
	public List<CarAssetDto> getSecondaryOperations() {
		return carMapper.getSecondaryOperations();
	}

	@Override
	public List<CarAssetDto> getSell() {
		return carMapper.getSell();
	}

	@Override
	public List<CarAssetDto> getInStockActuallyInStock() {
		return carMapper.getInStockActuallyInStock();
	}

	@Override
	public List<CarAssetDto> getInRoadVehicle() {
		return carMapper.getInRoadVehicle();
	}

	@Override
	public List<CarAssetDto> getInStockInLawsuit() {
		return carMapper.getInStockInLawsuit();
	}
}
